//Copyright (c) 2009, Sandeep Datta
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are permitted provided 
//that the following conditions are met:
//
//* Redistributions of source code must retain the above copyright notice, this list of conditions and 
//the following disclaimer.
//
//* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 
//the following disclaimer in the documentation and/or other materials provided with the distribution.
//
//* Neither the name of Sandeep Datta nor the names of its contributors may be used to endorse or 
//promote products derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
//IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
//FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
//WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


// MSIWrapper.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"

using namespace ATL;


#import "progid:WindowsInstaller.Installer" no_namespace

[emitidl];

//The following is required...since we need the definition for the Installer interface
//and the types used by it.
[importlib("msi.dll")];//Assumption: MSI.DLL is in the same path as the MSIWrapper project file.

[
	coclass,
	implements(interfaces={Installer}),
	threading(apartment),
	vi_progid("SharpInstall.MSIWrapper"),
	progid("SharpInstall.MSIWrapper.1"),
	version(1.0),
	uuid("62C70001-16A2-4fef-B0F5-6AD0092E5475"),
	helpstring("A wrapper for WindowsInstaller.Installer")
]
class ATL_NO_VTABLE MSIWrapper : public Installer
{
private:
	InstallerPtr _installer;

public:
	HRESULT FinalConstruct()
	{
		//NOTE: The following code fragment is correct since the
		//UUIDs of the installer interface and coclass are the same!
		//This is infact the raison detre for this wrapper project
		//since the TLB file inside the MSI.dll COM DLL does not
		//specify a co-class. 
		
		//The Installer cannot be instantiated in C# etc. code if there
		//is no co-class.

		//Also note trying to manually add a co-class
		//by modifying the reverse engineered IDL file will not 
		//work because the MIDL compiler complains about duplicate
		//UUIDS.
		_installer.CreateInstance(__uuidof(Installer));
		return S_OK;
	}

	// Methods:
	RecordPtr CreateRecord (
		long Count )
	{
		return _installer->CreateRecord(Count);
	}


	SessionPtr OpenPackage (
		const _variant_t & PackagePath,
		long Options )
	{
		_installer->OpenPackage(PackagePath, Options);
	}


	SessionPtr OpenProduct (
		_bstr_t ProductCode )
	{
		return _installer->OpenProduct(ProductCode);
	}


	DatabasePtr OpenDatabase (
		_bstr_t DatabasePath,
		const _variant_t & OpenMode )
	{
		
		return _installer->OpenDatabase(DatabasePath, OpenMode);
	}


	SummaryInfoPtr GetSummaryInformation (
		_bstr_t PackagePath,
		long UpdateCount )
	{
		return _installer->GetSummaryInformation(PackagePath, UpdateCount);
	}


	HRESULT EnableLog (
		_bstr_t LogMode,
		_bstr_t LogFile )
	{
		return _installer->EnableLog(LogMode, LogFile);
	}


	HRESULT InstallProduct (
		_bstr_t PackagePath,
		_bstr_t PropertyValues )
	{
		return _installer->InstallProduct(PackagePath, PropertyValues);
	}


	_bstr_t GetVersion ( )
	{
		return _installer->GetVersion();
	}


	RecordPtr LastErrorRecord ( )
	{
		return _installer->LastErrorRecord();
	}


	_bstr_t RegistryValue (
		const _variant_t & Root,
		_bstr_t Key,
		const _variant_t & Value = vtMissing )
	{
		return _installer->RegistryValue(Root, Key, Value);
	}


	long FileAttributes (
		_bstr_t FilePath )
	{
		return _installer->FileAttributes(FilePath);
	}


	long FileSize (
		_bstr_t FilePath )
	{
		return _installer->FileSize(FilePath);
	}


	_bstr_t FileVersion (
		_bstr_t FilePath,
		const _variant_t & Language = vtMissing )
	{
		return _installer->FileVersion(FilePath, Language);
	}


	_bstr_t GetEnvironment (
		_bstr_t Variable )
	{
		return _installer->GetEnvironment(Variable);
	}


	void PutEnvironment (
		_bstr_t Variable,
		_bstr_t _arg2 )
	{
		return _installer->PutEnvironment(Variable, _arg2);
	}


	enum MsiInstallState GetProductState (
		_bstr_t Product )
	{
		return _installer->GetProductState(Product);
	}


	_bstr_t GetProductInfo (
		_bstr_t Product,
		_bstr_t Attribute )
	{
		return _installer->GetProductInfo(Product, Attribute);
	}


	HRESULT ConfigureProduct (
		_bstr_t Product,
		long InstallLevel,
		enum MsiInstallState InstallState )
	{
		return _installer->ConfigureProduct(Product, InstallLevel, InstallState);
	}


	HRESULT ReinstallProduct (
		_bstr_t Product,
		enum MsiReinstallMode ReinstallMode )
	{
		return _installer->ReinstallProduct(Product, ReinstallMode);
	}


	HRESULT CollectUserInfo (
		_bstr_t Product )
	{
		return _installer->CollectUserInfo(Product);
	}


	HRESULT ApplyPatch (
		_bstr_t PatchPackage,
		_bstr_t InstallPackage,
		enum MsiInstallType InstallType,
		_bstr_t CommandLine )
	{
		return _installer->ApplyPatch(PatchPackage, InstallPackage, InstallType, CommandLine);
	}

	_bstr_t GetFeatureParent (
		_bstr_t Product,
		_bstr_t Feature )
	{
		return _installer->GetFeatureParent(Product, Feature);
	}

	enum MsiInstallState GetFeatureState (
		_bstr_t Product,
		_bstr_t Feature )
	{
		return _installer->GetFeatureState(Product, Feature);
	}


	HRESULT UseFeature (
		_bstr_t Product,
		_bstr_t Feature,
		enum MsiInstallMode InstallMode )
	{
		return _installer->UseFeature(Product, Feature, InstallMode);
	}


	long GetFeatureUsageCount (
		_bstr_t Product,
		_bstr_t Feature )
	{
		return _installer->GetFeatureUsageCount(Product, Feature);
	}

	DATE GetFeatureUsageDate (
		_bstr_t Product,
		_bstr_t Feature )
	{
		return _installer->GetFeatureUsageDate(Product, Feature);
	}


	HRESULT ConfigureFeature (
		_bstr_t Product,
		_bstr_t Feature,
		enum MsiInstallState InstallState )
	{
		return _installer->ConfigureFeature(Product, Feature, InstallState);
	}


	HRESULT ReinstallFeature (
		_bstr_t Product,
		_bstr_t Feature,
		enum MsiReinstallMode ReinstallMode )
	{
		return _installer->ReinstallFeature(Product, Feature, ReinstallMode);
	}


	_bstr_t ProvideComponent (
		_bstr_t Product,
		_bstr_t Feature,
		_bstr_t Component,
		long InstallMode )
	{
		return _installer->ProvideComponent(Product, Feature, Component, InstallMode);
	}


	_bstr_t GetComponentPath (
		_bstr_t Product,
		_bstr_t Component )
	{
		return _installer->GetComponentPath(Product, Component);
	}


	_bstr_t ProvideQualifiedComponent (
		_bstr_t Category,
		_bstr_t Qualifier,
		long InstallMode )
	{
		return _installer->ProvideQualifiedComponent(Category, Qualifier, InstallMode);
	}


	_bstr_t GetQualifierDescription (
		_bstr_t Category,
		_bstr_t Qualifier )
	{
		return _installer->GetQualifierDescription(Category, Qualifier);
	}


	StringListPtr GetComponentQualifiers (
		_bstr_t Category )
	{
		return _installer->GetComponentQualifiers(Category);
	}


	StringListPtr GetProducts ( )
	{
		return _installer->GetProducts();
	}


	StringListPtr GetFeatures (
		_bstr_t Product )
	{
		return _installer->GetFeatures(Product);
	}


	StringListPtr GetComponents ( )
	{
		return _installer->GetComponents();
	}


	StringListPtr GetComponentClients (
		_bstr_t Component )
	{
		return _installer->GetComponentClients(Component);
	}


	StringListPtr GetPatches (
		_bstr_t Product )
	{
		return _installer->GetPatches(Product);
	}


	StringListPtr GetRelatedProducts (
		_bstr_t UpgradeCode )
	{
		return _installer->GetRelatedProducts(UpgradeCode);
	}


	_bstr_t GetPatchInfo (
		_bstr_t Patch,
		_bstr_t Attribute )
	{
		return _installer->GetPatchInfo(Patch, Attribute);
	}


	_bstr_t GetPatchTransforms (
		_bstr_t Product,
		_bstr_t Patch )
	{
		return _installer->GetPatchTransforms(Product, Patch);
	}


	HRESULT AddSource (
		_bstr_t Product,
		_bstr_t User,
		_bstr_t Source )
	{
		return _installer->AddSource(Product, User, Source);
	}


	HRESULT ClearSourceList (
		_bstr_t Product,
		_bstr_t User )
	{
		return _installer->ClearSourceList(Product, User);
	}


	HRESULT ForceSourceListResolution (
		_bstr_t Product,
		_bstr_t User )
	{
		return _installer->ForceSourceListResolution(Product, User);
	}


	RecordPtr GetGetShortcutTarget (
		_bstr_t ShortcutPath )
	{
		return _installer->GetGetShortcutTarget(ShortcutPath);
	}


	RecordPtr FileHash (
		_bstr_t FilePath,
		long Options )
	{
		return _installer->FileHash(FilePath, Options);
	}


	SAFEARRAY * FileSignatureInfo (
		_bstr_t FilePath,
		long Options,
		enum MsiSignatureInfo Format )
	{
		return _installer->FileSignatureInfo(FilePath, Options, Format);
	}


	HRESULT RemovePatches (
		_bstr_t PatchList,
		_bstr_t Product,
		enum MsiInstallType UninstallType,
		_bstr_t PropertyList )
	{
		return _installer->RemovePatches(PatchList, Product, UninstallType, PropertyList);
	}


	HRESULT ApplyMultiplePatches (
		_bstr_t PatchPackage,
		_bstr_t Product,
		_bstr_t PropertiesList )
	{
		return _installer->ApplyMultiplePatches(PatchPackage, Product, PropertiesList );
	}


	HRESULT GetProduct (
		_bstr_t Product,
		_bstr_t UserSid,
		enum MsiInstallContext iContext,
	struct Product * * retval )
	{
		return _installer->GetProduct(Product, UserSid, iContext, retval);
	}


	HRESULT GetPatch (
		_bstr_t PatchCode,
		_bstr_t ProductCode,
		_bstr_t UserSid,
		enum MsiInstallContext iContext,
	struct Patch * * retval )
	{
		return _installer->GetPatch(PatchCode, ProductCode, UserSid, iContext, retval);
	}


	RecordListPtr GetProductsEx (
		_bstr_t Product,
		_bstr_t UserSid,
		long Contexts )
	{
		return _installer->GetProductsEx(Product, UserSid, Contexts);
	}


	RecordListPtr GetPatchesEx (
		_bstr_t Product,
		_bstr_t UserSid,
		long Contexts,
		long filter )
	{
		return _installer->GetPatchesEx (Product, UserSid, Contexts, filter);
	}


	_bstr_t ExtractPatchXMLData (
		_bstr_t PatchPath )
	{
		return _installer->ExtractPatchXMLData(PatchPath);
	}

	////////IDispatch implementation////////

	HRESULT STDMETHODCALLTYPE GetTypeInfoCount( 
		/* [out] */ UINT *pctinfo)
	{
		return _installer->GetTypeInfoCount(pctinfo);
	}



	HRESULT STDMETHODCALLTYPE GetTypeInfo( 
		/* [in] */ UINT iTInfo,
		/* [in] */ LCID lcid,
		/* [out] */ ITypeInfo **ppTInfo)
	{
		return _installer->GetTypeInfo(iTInfo, lcid, ppTInfo);
	}



	HRESULT STDMETHODCALLTYPE GetIDsOfNames( 
		/* [in] */ REFIID riid,
		/* [size_is][in] */ LPOLESTR *rgszNames,
		/* [in] */ UINT cNames,
		/* [in] */ LCID lcid,
		/* [size_is][out] */ DISPID *rgDispId)
	{
		return _installer->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId);
	}



	HRESULT STDMETHODCALLTYPE Invoke( 
		/* [in] */ DISPID dispIdMember,
		/* [in] */ REFIID riid,
		/* [in] */ LCID lcid,
		/* [in] */ WORD wFlags,
		/* [out][in] */ DISPPARAMS *pDispParams,
		/* [out] */ VARIANT *pVarResult,
		/* [out] */ EXCEPINFO *pExcepInfo,
		/* [out] */ UINT *puArgErr)
	{
		return _installer->Invoke( dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
	}
};
